﻿using System.Web;
using System.Web.SessionState;
using cludg.Infrastructure.Core.Logging;
using System;
using NHibernate;
using nsadv.Statistic.Repository.NHibernate;
using nsadv.Statistic.Repository.NHibernate.Sessions;
using nsadv.Statistic.Web.Notifications.Application;

namespace nsadv.Statistic.Web.Sessions
{
	public class NHibernateSessionController_PerHttpSession : INHibernateSessionController, IDisposable
	{
		protected readonly ILogger Logger;
		protected readonly NHibernateController Controller;
		protected readonly IApplicationNotifier ApplicationNotifier;

		public NHibernateSessionController_PerHttpSession(
			NHibernateController controller, 
			IApplicationNotifier applicationNotifier,
			ILogger logger)
		{
			Controller = controller;
			ApplicationNotifier = applicationNotifier;
			Logger = logger;

			ApplicationNotifier.SessionEnd += ApplicationNotifier_SessionEnd;
		}

		void ApplicationNotifier_SessionEnd(object sender, SessionEventArgs e)
		{
			var session = e.Session["NHibernateSession"] as ISession;
			if (session == null) return;

			e.Session.Remove("NHibernateSession");
			session.Dispose();
			Logger.Info("Dispose NHibernate session on end Http session");
		}

		protected HttpSessionState HttpSession
		{
			get
			{
				return HttpContext.Current.Session;
			}
		}

		protected  ISession CurrentSession
		{
			get { return HttpSession["NHibernateSession"] as ISession; }
			set { HttpSession["NHibernateSession"] = value; }
		}

		protected void CheckSession()
		{
			if (CurrentSession == null)
			{
				CurrentSession = Controller.OpenSession();
				CurrentSession.FlushMode = FlushMode.Commit;
				Logger.Info("Open NHibernate session");
			}
		}

		public ISession Current
		{
			get
			{
				CheckSession();

				if (!CurrentSession.IsConnected)
					CurrentSession.Reconnect();

				return CurrentSession;
			}
		}

		public void Reset()
		{
			CurrentSession = null;
			Logger.Info("NHibernate session reset");
		}

		public void Dispose()
		{
			ApplicationNotifier.SessionEnd -= ApplicationNotifier_SessionEnd;
		}
	}
}
